\bibliographystyle{gbt7714-2005}

\chapter{cookie与session}
\epigraphhead[60]{\epigraph{小时候，乡愁是一枚小小的邮票，我在这头，母亲在那头。}{\textit{节选自余光中《乡愁》}}}

在工作中，Web服务器可能需要同时与数千个不同的客户端进行对话，这样，服务器就必须记录下它们在与谁在交谈，而不是所有的请求都来自匿名的客户端。

HTTP最初是一个匿名、无状态的请求相应协议，服务器处理来自客户端的请求，然后向客户端回送一条响应。\cite{Gourley，2012}现代的Web站点需要提供个性化的信息，如推荐信息、用户购物信息、在线统计等等。借助于cookie机制，Web站点就能识别用户，保存个人信息。

\section{cookie}
cookie 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。Cookie最初是由网景公司开发，现在所有浏览器都支持这种技术。

\subsection{cookie的工作原理}
cookie是服务器存储在用户计算机中的一个文本文件，cookie由“名字=值”这样的信息构成，通过 set-cookie HTTP相应首部将其存储到用户端。当用户访问一个站点时，浏览器会将存储的cookie传送到站点服务器，这样服务器就能识别出这个用户了。具体如下表\ref{fig:cookie}：
\begin{figure}[htbp]
	\centering
	\includegraphics[width=120mm]{raw/cookie.pdf}
	\caption{Cookie运行机制}
	\label{fig:cookie}
\end{figure}

cookie的基本思想就是让浏览器积累一组服务器特有的信息，每次访问服务器时，将这些信息提供给它。我们可以在cookie中存放任意文本信息。

\subsection{cookie的属性}
现在使用的cookie规范有两个不同的版本：cookie版本0和cookie版本1，后者应用不如前者广泛。
版本0的cookie的内容如下：\cite{netscape，2014}
\begin{lstlisting}
Set-Cookie: NAME=VALUE; expires=DATE;
path=PATH; domain=DOMAIN_NAME; secure
\end{lstlisting}

以下是一个cookie的实例：
\begin{figure}[htbp]
	\centering
	\includegraphics{raw/cookie.jpg}
	\caption{Cookie属性实例}
	\label{fig:cookieproperty}
\end{figure}

\subsubsection{NAME=VALUE}
该属性是必须的，name和value都是字符序列，除非包含在双引号内，否则不包括分号、逗号、等号和空格。
\subsubsection{expires}
可选属性。该属性指定一个日期字符串，用来定义cookie的实际生存期。如果不指定，cookie就会在用户会话结束时过期。
\subsubsection{domain}
可选属性。浏览器只向指定域中的服务器主机名发送cookie。默认为浏览器当前访问的服务器主机名。
\subsubsection{path}
可选属性。该属性可为服务器上特定的文档分配cookie。路径“/”表示与域名中所有内容都匹配。
\subsubsection{secure}
可选属性。如果包含该属性，就只有在HTTP使用SSL安全链接时才发送cookie。

\subsection{cookie与隐私}
浏览器保存着不同网站的成百上千个cookie，这些cookie信息可能涉及用户浏览行为、购物历史等信息。但浏览器不会将每个cookie都发送给所有的站点，浏览器只向服务器发送服务器本身产生的cookie。也就是说，baidu.com产生的cookie信息不会发送到google.com或qq.com。

但是，很多Web站点都与第三方厂商达成协议，由其来管理广告，这些广告被做成Web站点的一个组成部分，这样，当用户访问含有第三方厂商广告的Web站点时（由于域是匹配的），第三方厂商也能收集用户cookie，暗地里构建一个用户档案和浏览习惯的详尽数据集。

现代的浏览器都允许用户对隐私特性进行设置，以限制第三方cookie的使用，但用户如果完全禁止cookie，就不能使用网站的个性化服务。可以这样理解，用户如果要免费使用网站的一些功能，就必须出让自己的一部分隐私。

\subsection{在PHP中设置和管理cookie}
在PHP中常用setcookie函数设置cookie属性，任何从客户端发送的 cookie 都会被自动包括进 \$\_COOKIE 自动全局数组。
\begin{lstlisting}
<?php
setcookie('name', 'yangjh');
echo $_COOKIE['name'];
var_dump($_COOKIE);
?>
\end{lstlisting}

\section{session}
虽然cookie能达到识别用户身份的目的，但由于cookie保存在客户端，因此，就存在伪造用户信息的弊端。而session 是在服务器端保存用户信息，这样就大大增加了安全性。

\subsection{session机制}
一个访问者访问你的 web 网站将被分配一个唯一的 id，就是所谓的会话 id。 这个 id 可以存储在用户端的一个 cookie 中，同时也被保存在服务器端，当一个访问者访问你的网站，通过检查当前会话 id 是否是先前发送的请求创建，如果是， 那么先前保存的环境将被重建。\cite{PHPGroup，2014}具体见下图\ref{fig:session}：

\begin{figure}[htbp]
	\centering
	\includegraphics[width=120mm]{raw/session.pdf}
	\caption{session运行机制}
	\label{fig:session}
\end{figure}

\subsection{在PHP中使用session}
在PHP中，设置session内容之前，需先使用session\_start函数启用session，然后使用全局数组\$\_SESSION进行内容设置，如：
\begin{lstlisting}
<?php
session_start();
$_SESSION['name'] = 'yangzh';
?>
\end{lstlisting}

上面的代码运行后，服务器端将产生一个临时文本文件，如sess\_uik2df2r5tqcv9t2n0i5nrfg04，在这个文件中，保存session设置的属性及其值。
\begin{lstlisting}
name|s:6:"yangzh";
\end{lstlisting}

当需要销毁session中的某些内容时，可以使用unset函数：
\begin{lstlisting}
<?php
session_start();
unset($_SESSION['name']);
?>
\end{lstlisting}

当用户退出登录状态时，使用session\_destroy函数彻底销毁session：
\begin{lstlisting}
<?php
session_start();
session_destroy();
?>
\end{lstlisting}

\bibliography{../../bib/yangjh}
